import { defineComponent, onMounted, PropType, provide, ref, StyleValue, toRef } from 'vue'
import { JustifyContentProperty } from 'csstype'
import { useMergedState, useNameSpace } from '../_util/hooks'
import TabPane from './TabPane'
import Tabbar, { Tab } from './Tabbar'
import { getKey, normalize } from './utils'
import { TabsContextKey, TabsContextProps } from './interface'

export type TabbarType = 'bar' | 'line' | 'card' | 'border-card' | 'segment'

const preCls = 'x-tabs'

export default defineComponent({
  name: preCls,
  props: {
    value: [String, Number],
    defaultValue: [String, Number],
    size: { type: String as PropType<'small' | 'medium' | 'large'>, default: 'medium' },
    barStyle: [String, Object, Array] as PropType<StyleValue>,
    justify: String as PropType<JustifyContentProperty>,
    type: { type: String as PropType<TabbarType>, default: 'bar' },
    beforeLeave: Function as PropType<(name: string | number, oldName: string | number) => boolean | Promise<boolean>>,
    tabs: Array as PropType<Tab[]>
  },
  emits: ['update:value'],
  setup(props, { emit, slots }) {
    const ns = useNameSpace(preCls)

    const valueRef = useMergedState(toRef(props, 'value'), ref(props.value ?? props.defaultValue))
    onMounted(() => {
      if (valueRef.value == null) valueRef.value = getKey(tabpanes.value[0]) ?? 0
    })

    const tabpanes = ref([]) as TabsContextProps['tabpanes']

    provide(TabsContextKey, {
      value: valueRef,
      tabpanes
    })

    async function onChange(key: string) {
      if (valueRef.value === key) return
      if (typeof props.beforeLeave === 'function') {
        const bool = await props.beforeLeave(key, valueRef.value!)
        if (!bool) return
      }
      valueRef.value = key
      emit('update:value', key)
    }

    return () => (
      <div class={[ns.b(), ns.m(props.type), ns.m(props.size)]}>
        <Tabbar value={valueRef} tabs={tabpanes} type={props.type} onChange={onChange} style={`justify-content: ${props.justify}`} />
        {slots.default?.()}
        {props.tabs?.map(e => <TabPane {...normalize(e)} />)}
      </div>
    )
  }
})
